﻿'This file is part of Alpha.
'
'   Alpha is free software: you can redistribute it and/or modify
'   it under the terms of the GNU Lesser General Public License as published by
'   the Free Software Foundation, either version 3 of the License, or
'   (at your option) any later version.
'
'   Alpha is distributed in the hope that it will be useful,
'   but WITHOUT ANY WARRANTY; without even the implied warranty of
'   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'   GNU Lesser General Public License for more details.
'
'   You should have received a copy of the GNU Lesser General Public License
'   along with Alpha.  If not, see <http://www.gnu.org/licenses/>.

Namespace Controllers
    Public Class iTunes
        Inherits Controller



#Region " Properties "


        Private itunes As iTunesLib.iTunesApp

        Private playing As Boolean
        Private paused As Boolean

        Private comptrack As iTunesLib.IITTrack

        Private WithEvents timer As System.Timers.Timer

#End Region


#Region " Controller Requirements "
        <Security.SecurityTreatAsSafe()> _
        Public Sub New()
            Dim itunesprocess As IntPtr = NativeMethods.FindWindow("", "iTunes")
            If itunesprocess.ToInt32 = 0 Then
                Throw New PlayerNotRunningException
            Else
                itunes = New iTunesLib.iTunesApp
                Update()
                timer = New System.Timers.Timer(1000)
                timer.Start()
            End If
        End Sub

        Public Overrides ReadOnly Property Version() As String
            Get
                Return "iTunes Controller v1.1"
            End Get
        End Property

        Public Overrides ReadOnly Property SupportedActions() As Collections.ObjectModel.ReadOnlyCollection(Of Action)
            Get
                Dim list As System.Collections.Generic.List(Of Action) = New System.Collections.Generic.List(Of Action)
                list.Add(Action.Play)
                list.Add(Action.Pause)
                list.Add(Action.PlayPause)
                list.Add(Action.StopPlayback)
                list.Add(Action.PreviousTrack)
                list.Add(Action.NextTrack)
                list.Add(Action.BackTrack)
                list.Add(Action.VolumeUp)
                list.Add(Action.VolumeDown)
                list.Add(Action.ToggleMute)
                list.Add(Action.GetVolume)
                list.Add(Action.SetVolume)
                list.Add(Action.TrackTitle)
                list.Add(Action.TrackArtist)
                list.Add(Action.TrackAlbum)
                list.Add(Action.TrackLength)
                list.Add(Action.TrackTimeElapsed)
                list.Add(Action.TrackYear)
                list.Add(Action.TrackGenre)
                list.Add(Action.AlbumTrackNo)
                list.Add(Action.AlbumTotalTracks)
                list.Add(Action.AlbumDiskNo)
                list.Add(Action.AlbumTotalDisks)
                Return New Collections.ObjectModel.ReadOnlyCollection(Of Action)(list)
            End Get
        End Property


#End Region


#Region " Playback "


        Public Overrides Sub NextTrack()
            If playing Then
                itunes.NextTrack()
            Else
                Throw New NotPlayingException()
            End If
        End Sub

        Public Overrides Sub Pause()
            If playing And (True <> paused) Then
                itunes.Pause()
                paused = True
                playing = False
            ElseIf paused Then
                Throw New AlreadyPausedException()
            Else
                Throw New NotPlayingException()
            End If
        End Sub

        Public Overrides Sub Play()
            If paused Or (True <> playing) Then
                itunes.Play()
                playing = True
                paused = False
            ElseIf playing Then
                Throw New AlreadyPlayingException()
            End If
        End Sub

        Public Overrides Sub PlayPause()
            If Not paused And Not playing Then
                Throw New NotPlayingException()
            End If
            itunes.PlayPause()
            If playing Then
                playing = False
            Else
                playing = True
            End If
            If paused Then
                paused = False
            Else
                paused = True
            End If
        End Sub

        Public Overrides Sub PreviousTrack()
            If playing Then
                itunes.PreviousTrack()
            Else
                Throw New NotPlayingException()
            End If
        End Sub

        Public Overrides Sub BackTrack()
            If playing Then
                itunes.BackTrack()
            Else
                Throw New NotPlayingException()
            End If
        End Sub

        Public Overrides Sub StopPlayback()
            If playing Then
                itunes.Stop()
                paused = False
                playing = False
            Else
                Throw New NotPlayingException()
            End If
        End Sub


#End Region


#Region " Volume "

        Public Overrides Sub VolumeDown()
            If itunes.SoundVolume < 10 Then
                itunes.SoundVolume = 0
            ElseIf itunes.SoundVolume = 0 Then
                Throw New MinVolumeException
            Else
                itunes.SoundVolume = itunes.SoundVolume - 10
            End If
        End Sub

        Public Overrides Sub VolumeUp()
            If itunes.SoundVolume > 90 Then
                itunes.SoundVolume = 100
            ElseIf itunes.SoundVolume = 100 Then
                Throw New MaxVolumeException
            Else
                itunes.SoundVolume = itunes.SoundVolume + 10
            End If
        End Sub

        Public Overrides Sub ToggleMute()
            If itunes.Mute Then
                itunes.Mute = False
            Else
                itunes.Mute = True
            End If
        End Sub

        Public Overrides Property Mute() As Boolean
            Get
                Return itunes.Mute
            End Get
            Set(ByVal mute As Boolean)
                itunes.Mute = mute
            End Set
        End Property

#End Region

#Region " Track Info "

        Public Overrides ReadOnly Property Track() As Track
            Get
                Return New Track With {.Title = itunes.CurrentTrack.Name, _
                                        .Artist = itunes.CurrentTrack.Artist, _
                                        .Album = itunes.CurrentTrack.Album, _
                                        .Length = itunes.CurrentTrack.Duration, _
                                        .AlbumTrackNo = itunes.CurrentTrack.TrackNumber, _
                                        .AlbumTotalTracks = itunes.CurrentTrack.TrackCount, _
                                        .AlbumDiskNo = itunes.CurrentTrack.DiscNumber, _
                                        .AlbumTotalDisks = itunes.CurrentTrack.DiscCount}
            End Get
        End Property

#End Region

#Region " Event Support "

        Public Shadows Event TrackChanged()

        Private Sub Update() Handles timer.Elapsed

            'Update Play and Pause Switches
            ' TODO: Find out how to check for paused = TRUE
            If itunes.PlayerState = iTunesLib.ITPlayerState.ITPlayerStatePlaying Then
                playing = True
            ElseIf itunes.PlayerState = iTunesLib.ITPlayerState.ITPlayerStateStopped Then
                playing = False
                paused = False
            End If

            'Update Track Information (if changed)
            If Not (comptrack Is itunes.CurrentTrack) Then
                comptrack = itunes.CurrentTrack()
                RaiseEvent TrackChanged()
            End If

        End Sub

#End Region


#Region " IDisposable Support"
        Private disposedValue As Boolean

        ' IDisposable
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    timer.Dispose()
                End If
                itunes = Nothing
                GC.Collect()
            End If
            Me.disposedValue = True
        End Sub

#End Region


    End Class
End Namespace
